package jm.algorithm.sort;

import javafx.scene.transform.Shear;

import java.text.DecimalFormat;
import java.util.Arrays;

/**
 * @Description 排序算法公共父类
 * @date 2022/5/2 9:17
 */
public abstract class Sort<T extends Comparable<T>> implements Comparable<Sort<T>>{

    // 数组
    protected T[] arr;
    // 比较次数
    private int cmpCount;
    // 交换次数
    private int swapCount;
    // 执行时间
    private long time;
    // 小数点格式化
    private DecimalFormat fmt = new DecimalFormat("#.00");

    // 父类构造函数，调用sort方法，由子类去实现
    public void sort(T[] arr){
        if (arr == null || arr.length < 2) return;
        this.arr = arr;
        long begin = System.currentTimeMillis();
        sort();
        time  = System.currentTimeMillis() - begin;
    }

    /**
     * 比较方法，按照时间 - 比较次数 - 交换次数。
     * @param o
     * @return
     */
    @Override
    public int compareTo(Sort<T> o) {
        int result = (int) (time - o.time);
        if (result != 0) return  result;

        result = cmpCount - o.cmpCount;
        if (result != 0) return result;

        result = swapCount - o.swapCount;
        return result;
    }

    /**
     * 子类实现方法
     */
    protected abstract void sort();

    /**
     * 比较索引位置的大小
     * @param i1 索引1
     * @param i2 索引2
     * @return 等于0 : i1 == i2 ; 小于0 i1 < i2 ; 大于0 i1 > i2
     */
    protected int cmp(int i1, int i2){
        cmpCount++;
        return arr[i1].compareTo(arr[i2]);
    }

    /**
     * 比较元素的大小
     * @param v1 值1
     * @param v2 值2
     * @return 等于0 : i1 == i2 ; 小于0 i1 < i2 ; 大于0 i1 > i2
     */
    protected int cmp(T v1, T v2){
        cmpCount++;
        return v1.compareTo(v2);
    }

    /**
     * 交换索引位置的元素
     * @param i1 索引1
     * @param i2 索引2
     */
    protected void swap(int i1, int i2){
        swapCount++;
        T tmp = arr[i1];
        arr[i1] = arr[i2];
        arr[i2] = tmp;
    }

    /**
     * 将传入较长的数转为位数
     * @param number
     * @return
     */
    private String numberString(int number) {
        if (number < 10000) return "" + number;

        if (number < 100000000) return fmt.format(number / 10000.0) + "万";
        return fmt.format(number / 100000000.0) + "亿";
    }

    /**
     * 判断稳定性
     * @return
     */
    private boolean isStable(){
        if (this instanceof CountingSortPro) return true;
        if (this instanceof CountingSort) return true;
        if (this instanceof ShellSort) return false;
        if (this instanceof RadixSort) return true;
        // 根据student类型测试，如果年龄相同的分数呈递增状态则是稳定性排序。
        Student[] students = new Student[20];
        for (int i = 0; i < students.length; i++) {
            students[i] = new Student(i * 10, 10);
        }
        sort((T[]) students);
        for (int i = 1; i < students.length; i++) {
            int score = students[i].score;
            int prevScore = students[i - 1].score;
            if (score != prevScore + 10) return false;
        }
        return true;
    }

    @Override
    public String toString() {
        String timeStr = "耗时：" + (time / 1000.0) + "s(" + time + "ms)";
        String compareCountStr = "比较：" + numberString(cmpCount);
        String swapCountStr = "交换：" + numberString(swapCount);
        String stableStr = "稳定性：" + isStable() + " ";
        return "【" + getClass().getSimpleName() + "】\n"
                + stableStr + " \t"
                + timeStr + " \t"
                + compareCountStr + "\t "
                + swapCountStr + "\n"
                + "------------------------------------------------------------------";
    }
}
